package devices

import (
	"adai.design/homeserver/log"
	"net"
	"bufio"
	"adai.design/homeserver/db"
)

type PackageObserver interface {
	Handle(pkg *MessagePkg)
}

type Receptions struct {
	devices map[string]*Reception

	register   chan *Reception
	unregister chan *Reception

	// 接收到的包裹和需要发送设备的包裹
	recPkg  chan *MessagePkg
	sendPkg chan *MessagePkg

	observers	[]PackageObserver

	address string
	end     chan bool
}

var workers = Receptions{}

// 接收连接
func (ws *Receptions) listen() {
	l, err := net.Listen("tcp", ":6666")
	if err != nil {
		log.Panic(err)
		ws.end <- true
	}

	for {
		conn, err := l.Accept()
		if err != nil {
			log.Panic(err)
			ws.end <- true
		}
		worker := &Reception{conn: conn, reader: bufio.NewReader(conn)}
		go worker.start(ws)
	}
}

func (ws *Receptions) online(register *db.Register) {
	pkg := &MessagePkg{
		DevId:  register.Id,
		HomeId: register.HomeId,
		Msg: &Message{
			Path: MsgPathContainer,
			Method: MsgMethodPut,
			State: ContainerStateOnline,
		},
	}
	register.Online()
	ws.recPkg <- pkg
}

func (ws *Receptions) offline(register *db.Register) {
	pkg := &MessagePkg{
		DevId:  register.Id,
		HomeId: register.HomeId,
		Msg: &Message{
			Path: MsgPathContainer,
			Method: MsgMethodPut,
			State: ContainerStateOffline,
		},
	}
	register.Offline()
	ws.recPkg <- pkg
}

// 连接管理
func (ws *Receptions) start() {
	ws.devices = make(map[string]*Reception, 0)
	ws.register = make(chan *Reception, 10)
	ws.unregister = make(chan *Reception, 10)
	ws.recPkg = make(chan *MessagePkg, 10)
	ws.sendPkg = make(chan *MessagePkg, 10)

	go ws.listen()

	for {
		select {
		// 设备在线消息
		case w, ok := <-ws.register:
			if ok {
				log.Info("(%s) online", w.register.Id)
				if old, ok := ws.devices[w.register.Id]; ok {
					if old != w {
						old.disconnect()
					}
				}
				ws.devices[w.register.Id] = w
				ws.online(w.register)
			}

		// 设备离线
		case w, ok := <-ws.unregister:
			if ok {
				if v, ok := ws.devices[w.register.Id]; ok {
					if v == w {
						log.Info("(%s) offline", w.register.Id)
						delete(ws.devices, w.register.Id)
						ws.offline(w.register)
					}
				}
				w.stop()
			}

		// 向设备发送消息
		case pkg, ok := <-ws.sendPkg:
			if ok {
				if dev, ok := ws.devices[pkg.DevId]; ok {
					dev.task <- pkg.Msg
				}
			}


		//设备发送回来的消息处理
		case pkg, ok := <- ws.recPkg:
			if ok {
				for _, observer := range workers.observers {
					observer.Handle(pkg)
				}
			}
		}
	}
}

func StartService(end chan bool) {
	log.Info("devices service established")

	workers.address = ":6666"
	workers.end = end
	go workers.start()
}

// 发送包裹
func SendPackage(pkg *MessagePkg) error {
	if workers.sendPkg != nil {
		workers.sendPkg <- pkg
	}
	return nil
}

// 监听包裹
func AddObserver(ob PackageObserver) error {
	workers.observers = append(workers.observers, ob)
	return nil
}

// 移除监听
func RemoveObserver(ob PackageObserver) error {
	for i, observer := range workers.observers {
		if observer == ob {
			workers.observers = append(workers.observers[:i], workers.observers[i+1:]...)
			return nil
		}
	}
	return nil
}